package cn.tedu.charging.order.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;

/**
 * rabbit-mq 配置类
 * 配置连接 连接信息,用户名 密码
 * 配置 交换机 Exchange 队列 Queue 绑定 通过Routingkey
 */
@Configuration
public class RabbitConfiguration {
    // Exchange 名称
    public static final String EXCHANGE_NAME = "charging_order-exchange";
    // 队列名称
    public static final String QUEUE_NAME = "charging_order-queue";
    // Routingkey
    public static final String ROUTING_KEY = "charging_order_routing_key";

    // 死信相关名称
    // Exchange 名称
    public static final String DEAD_LETTER_EXCHANGE_NAME = "dead_letter_charging_order-exchange";
    // 队列名称
    public static final String DEAD_LETTER_QUEUE_NAME = "dead_letter_charging_order-queue";
    // Routingkey
    public static final String DEAD_LETTER_ROUTING_KEY = "dead_letter_charging_order_routing_key";


    /**
     * 定义正常订单的Exchange
     */
    @Bean
    public DirectExchange orderExchange(){
        // 消息持久化 消息不能丢失
        Boolean durable = true;
        // 自动删除 一次性
        Boolean autoDelete = false;
        return new DirectExchange(EXCHANGE_NAME,durable,autoDelete);
    }

    /**
     * 定义正常订单的 Queue
     * 设置一下 超时时间
     */
    @Bean
    public Queue orderQueue(){
        // 1. 设置队列的最大长度
        Map<String, Object> args = new HashMap<>();
        // 设置消息的TTL存活时间，模拟充电充满需要 2 分钟
        Integer ttl = 2 * 60 * 1000;
        // 消息过期时间（毫秒） 当消息超过这个时间后，会被自动转发到死信队列
        args.put("x-message-ttl", ttl);
        // 设置queue的死信 Exchange   设置当消息过期后，要转发到哪个交换机
        args.put("x-dead-letter-exchange",DEAD_LETTER_EXCHANGE_NAME);
        // 设置 queue 和 死信 Exchange 绑定 routing-key    设置消息过期后，要转发到死信队列时使用的路由键
        args.put("x-dead-letter-routing-key",DEAD_LETTER_ROUTING_KEY);
        // 惰性队列，在消息很多的时候，把消息存储到磁盘，避免消息积压，占用内存   x-queue-mode - 队列模式
        args.put("x-queue-mode", "lazy");

        // 队列持久化
        Boolean durable = true;
        // 队列自动删除
        Boolean autoDelete = false;
        return new Queue(QUEUE_NAME,durable,false,autoDelete, args);
    }

    /**
     * 把 Queue 和 Exchange 通过 routing-key 进行绑定
     *  BindingBuilder 是 Spring Boot RabbitMQ的推荐方式
     */
    @Bean
    public Binding orderBinding(){
        return BindingBuilder
                .bind(orderQueue())
                .to(orderExchange())
                .with(ROUTING_KEY);
    }

    /**
     * 定义死信订单的Exchange
     */
    @Bean
    public DirectExchange deadLetterOrderExchange(){
        // 消息持久化 消息不能丢失
        Boolean durable = true;
        // 自动删除 一次性
        Boolean autoDelete = false;
        return new DirectExchange(DEAD_LETTER_EXCHANGE_NAME,durable,autoDelete);
    }

    /**
     * 定义死信订单的 Queue
     */
    @Bean
    public Queue deadLetterOrderQueue(){
        // 队列持久化
        Boolean durable = true;
        return new Queue(DEAD_LETTER_QUEUE_NAME,durable);
    }

    /**
     * 把 死信 Queue 和 死信 Exchange 通过 routing-key 进行绑定
     */
    @Bean
    public Binding deadLetterOrderBinding(){
        return BindingBuilder
                .bind(deadLetterOrderQueue())
                .to(deadLetterOrderExchange())
                .with(DEAD_LETTER_ROUTING_KEY);
    }

}
